using SharpDX;
using System;
using System.IO;
using System.Text;

namespace Engine.FileFormats3D.WR2TrafficFiles
{
    [Flags]
    public enum LaneSide
    {
        none,
        Left,
        Right
    }

    public struct StreetNode
    {
        #region Public Fields

        public float angle1;
        public float angle2;

        /// <summary>
        /// Inclination of the connected roads. the angle is in radians.
        /// </summary>
        public float inclinationInRadians;

        public LaneSide laneside;
        public float positionX;
        public float positionY;
        public float positionZ;

        #endregion Public Fields

        #region Private Fields

        private int index;
        private bool isPriorityStreet;

        #endregion Private Fields

        #region Public Constructors

        public StreetNode(int index, float X, float Y, float Z, float angleSinus, float inclinationAngleInRadian, float angleCosinus, bool isPriorityStreet)
        {
            this.index = index;
            this.positionX = X;
            this.positionY = Y;
            this.positionZ = Z;
            this.angle1 = angleSinus;
            this.angle2 = angleCosinus;
            this.inclinationInRadians = inclinationAngleInRadian;
            this.laneside = LaneSide.none;
            this.isPriorityStreet = isPriorityStreet;
        }

        #endregion Public Constructors

        #region Public Properties

        public bool IsPriorityStreet
        {
            get { return isPriorityStreet; }
            set { isPriorityStreet = value; }
        }

        public Vector3 Position
        {
            set
            {
                this.positionX = value.X;
                this.positionY = value.Y;
                this.positionZ = value.Z;
            }
            get
            {
                return new Vector3(this.positionX, this.positionY, this.positionZ);
            }
        }

        #endregion Public Properties

        #region Public Methods

        public static StreetNode FromStream(BinaryReader br, int index)
        {
            return new StreetNode(index, br.ReadSingle(), br.ReadSingle(), br.ReadSingle(), br.ReadSingle(), br.ReadSingle(), br.ReadSingle(), false);
        }

        public double GetDirectionInDegree()
        {
            double anglw = Math.Atan2(this.angle1, angle2) * 180 / Math.PI;
            if (anglw < 0.0f)
                anglw += 360.0;
            if (anglw > 360.0)
                anglw -= 360.0;
            return anglw;
        }

        public Vector3 GetPositionFromTangent(float tangentLength)
        {
            float newTangent = (tangentLength / (30.0f * 1.024f));

            Vector3 tangent = new Vector3(this.angle1 * newTangent, 0.0f, this.angle2 * newTangent);
            return tangent;
        }

        public void Save(BinaryWriter bw)
        {
            bw.Write(this.positionX);
            bw.Write(this.positionY);
            bw.Write(this.positionZ);
            bw.Write(this.angle1);
            bw.Write(this.inclinationInRadians);
            bw.Write(this.angle2);
        }

        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendLine("-StreetNode- " + index.ToString() + " ----------");
            sb.AppendLine("positionX:     " + positionX.ToString());
            sb.AppendLine("positionY:     " + positionY.ToString());
            sb.AppendLine("positionZ:       " + positionZ.ToString());
            sb.AppendLine("angle1:       " + angle1.ToString());
            sb.AppendLine("Neigung In Rad:       " + inclinationInRadians.ToString());
            sb.AppendLine("angle2:       " + angle2.ToString());
            sb.AppendLine("Mainstreet: " + this.isPriorityStreet.ToString());
            sb.AppendLine("-end-");

            return sb.ToString();
        }

        #endregion Public Methods
    }
}